package com.taglab.chic.atom.syndication.spring;

import com.taglab.chic.atom.AtomFeed;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
import org.springframework.web.servlet.mvc.LastModified;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import static javax.servlet.http.HttpServletResponse.SC_NOT_MODIFIED;
import java.util.Date;

import com.taglab.chic.mvc.spring.ETag;

/**
 * @author Markus Kobler
 */
public abstract class AtomSyndicationController extends AbstractController implements LastModified, ETag {

  private final static Logger logger = LoggerFactory.getLogger(AtomSyndicationController.class);

  private final static String FEED_ATTR_KEY = AtomSyndicationController.class.getName()+":AtomFeed";
  
  private String viewName;
  private AtomView atomView;
  private String atomFeedKey;

  private long maxAge = 60 * 60;       // 1 hour
  private int bufferSize = 100 * 1024; // 100k

  public void setViewName(String viewName) {
    this.viewName = viewName;
  }

  public void setAtomView(AtomView atomView) {
    this.atomView = atomView;
  }

  public void setAtomFeedKey(String atomFeedKey) {
    this.atomFeedKey = atomFeedKey;
  }

  @Override
  protected void initApplicationContext() throws BeansException {
    if( viewName == null ) {
      atomView = new AtomView();
      atomView.setBeanName("atomView");
      atomView.setServletContext(getServletContext());
      if( atomFeedKey == null ) atomFeedKey = "atomFeed";
      atomView.setAtomFeedKey(atomFeedKey);
      atomView.initApplicationContext();
    }
  }

  protected ModelAndView handleRequestInternal(HttpServletRequest request,
                                               HttpServletResponse response) throws Exception {

    String requestETag = request.getHeader("If-None-Match");
    String etag = getETag(request);
    if( requestETag != null ) {
      if( requestETag.equals( etag ) ) {
        response.setStatus(SC_NOT_MODIFIED);
        return null;
      } else {
        response.setHeader("Cache-Control", "max-age=0, must-revalidate");
      }
    }
    
    if( etag != null ) response.setHeader("ETag", etag);

    if( maxAge > -1 ) {
      response.addHeader("Cache-Control", "max-age="+maxAge);
      response.addDateHeader("Expires", new Date().getTime() + (maxAge*1000));
    }

    response.setBufferSize(bufferSize);
    
    ModelAndView modelAndview = new ModelAndView();
    
    if( atomView == null ) {
      modelAndview.setViewName(viewName);
    } else {
      modelAndview.setView(atomView);
    }

    AtomFeed feed = lookupFeed(request);

    if( feed != null ) {
      if( atomFeedKey == null ) {
        modelAndview.addObject(feed);
      } else {
        modelAndview.addObject(atomFeedKey, feed);
      }
    }
    
    return modelAndview;
  }

  public long getLastModified(HttpServletRequest request) {
    AtomFeed feed = lookupFeed(request);
    if( feed == null ) return -1;
    return feed.getUpdated().getTime();
  }

  public String getETag(HttpServletRequest request) {
    long time = getLastModified(request);
    return time != -1 ? "\""+ DigestUtils.md5Hex(Long.toString(time)) +"\"" : null;
  }

  private AtomFeed lookupFeed(HttpServletRequest request) {
    AtomFeed feed = (AtomFeed)request.getAttribute(FEED_ATTR_KEY);
    if( feed == null ) {
      feed = createFeed(request);
      request.setAttribute(FEED_ATTR_KEY, feed);
    }
    return feed;
  }

  protected abstract AtomFeed createFeed(HttpServletRequest request); /*{
    
    AtomFeed feed = new AtomFeed("http://www.taglab.com.com/syndication/test-feed.xml", "Test Atom Feed");
    feed.addLink(new Link("http://www.taglab.com/", "alternate", "application/xhtml+xml"));
    feed.addLink(new Link("http://www.taglab.com/syndication/atom", "self", "application/atom+xml"));
    feed.addAuthor(new Person("Markus Kobler", null, "http://www.taglab.com/"));
    feed.setRights("(c) copyright Markus Kobler 2009");
    feed.setSubTitle("Test Atom Feed Subtitle");
    feed.setIcon("http://www.taglab.com/favicon.ico");
    feed.setLogo("http://www.taglab.com/images/logo_taglab.png");
    feed.setUpdated(new Date(1237689352097l));

    AtomEntry entry = new AtomEntry("http://www.taglab.com/news/2009-03-01/", "Example Article", "This is the article foo bar baz");
    entry.addLink(new Link("http://www.taglab.com/news/2009-03-01/", "alternate"));
    entry.setContent("This is the entries content foo bar baz asdfsdf");    
    feed.addEntry(entry);
    
    entry = new AtomEntry("http://www.taglab.com/news/2009-03-02/", "Second Example Article", null, "Second!");
    entry.addLink(new Link("http://www.taglab.com/news/2009-03-02/", "alternate"));
    entry.setContent("Second Entry");
    feed.addEntry(entry);
    
    return feed;
  }*/

}
